package com.cqjtu.tto.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.cqjtu.tto.dao.mapper.FolderMapper;
import com.cqjtu.tto.dao.pojo.Folder;
import com.cqjtu.tto.dao.pojo.Project;
import com.cqjtu.tto.dao.pojo.SftpProperties;
import com.cqjtu.tto.service.FolderService;
import com.cqjtu.tto.utils.NumUtil;
import com.cqjtu.tto.vo.ErrorCode;
import com.cqjtu.tto.vo.Results;
import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.Arrays;
import java.util.List;

@Service
@Slf4j
public class FolderServiceImpl implements FolderService {

    @Autowired
    FolderMapper folderMapper;

    @Autowired
    SftpProperties config;

    private static final String SESSION_CONFIG_STRICT_HOST_KEY_CHECKING = "StrictHostKeyChecking";


    @Override
    public Results addFold(Project project) throws Exception {
        Long projectId = project.getProjectId();
        String projectName = project.getProjectName();
        Long userId = project.getUserId();
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("folder_name",projectName);                     //通过文件名称查询是否存在同名
        Folder folder = folderMapper.selectOne(queryWrapper);
        if(folder != null){
            return Results.fail(-500,"该项目文件已经存在！");
        }
        Folder folder1 = new Folder(NumUtil.nextPkId(),projectId,projectName,userId,null
                ,config.getRoot()+projectName,null);
        folderMapper.insert(folder1);
        this.createDirectory(projectName);
        return Results.success("文件添加成功！");
    }

    @Override
    public Results selectAll(Long builder_id) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("builder_id",builder_id);
        List list = folderMapper.selectList(queryWrapper);
        if (list.isEmpty()) {
            return Results.fail(ErrorCode.USER_NOT_EXIST.getCode(), "该主管未含有任何项目！");
        }
        return Results.success(list);
    }

    @Override
    public void packge(String pro_name) throws Exception {
        ChannelSftp sftp = this.createSftp();
        sftp.cd(config.getRoot());
        Session session = sftp.getSession();
        ChannelExec channelExec = (ChannelExec)session.openChannel("exec");
//        String url = "zip -r "+pro_name+".zip /home/sftp/";
//        "zip -r "+pro_name+".zip "+pro_name
        channelExec.setCommand("zip -r "+pro_name+".zip /211_project/"+pro_name);
        channelExec.connect(1000);
        InputStream in = channelExec.getInputStream();
        //命令执行结果
//        byte[] tmp = new byte[1024];
//        while (true) {
//            while (in.available() > 0) {
//                int i = in.read(tmp, 0, 1024);
//                if (i < 0) break;
//                //执行结果打印到程序控制台
//                System.out.print(new String(tmp, 0, i));
//            }
//            if (channelExec.isClosed()) {
//                if (in.available() > 0) continue;
//                //获取退出状态，状态0表示脚本被正确执行
//                System.out.println("exit-status: "+ channelExec.getExitStatus());
//                break;
//            }
//            try {
//                Thread.sleep(1000);
//            } catch (Exception ee) {
//            }
//        }
        channelExec.disconnect();
    }
    @Override
    public File downloadFile(String targetpath) throws Exception {
        ChannelSftp sftp = this.createSftp();
        sftp.cd(config.getRoot());                                         //寻找项目文件并打包
        OutputStream outputStream = null;
        try {
//            sftp.cd(config.getRoot());
//            log.info("Change path to {}", config.getRoot());

            File file = new File(targetpath.substring(targetpath.lastIndexOf("/")+1));
            outputStream = new FileOutputStream(file);
            sftp.get(targetpath,outputStream);

            log.info("Download file success. TargetPath: {}", targetpath);
            return file;

        } catch (SftpException e) {
            log.error("Download file failure. TargetPath: {}", targetpath, e);
            e.printStackTrace();
        } finally {
            if(outputStream != null){
                outputStream.close();
            }
            this.disconnect(sftp);
        }
        return  null;
    }

    //  创建sftp链接
    private ChannelSftp createSftp() throws Exception {
        JSch jSch = new JSch();
        log.info("Try to connect sftp["+config.getUsername()+"@"+config.getHost()+"],use password]"+config.getPassword()+"]");
        Session session = createSession(jSch, config.getHost(), config.getUsername(), config.getPort());
        session.setPassword(config.getPassword());
        session.connect(config.getSessionConnectTimeout());
        log.info("Session connected to {}.", config.getHost());
        Channel channel = session.openChannel(config.getProtocol());
        channel.connect(config.getChannelConnectedTimeout());
        log.info("Channel created to {}.", config.getHost());
        return (ChannelSftp) channel;
    }
    /**
     * 关闭连接
     *
     * @param sftp
     */
    private void disconnect(ChannelSftp sftp) {
        try {
            if (sftp != null) {
                if (sftp.isConnected()) {
                    sftp.disconnect();
                } else if (sftp.isClosed()) {
                    log.info("sftp is closed already");
                }
                if (null != sftp.getSession()) {
                    sftp.getSession().disconnect();
                }
            }
        } catch (JSchException e) {
            e.printStackTrace();
        }
    }

    private Session createSession(JSch jsch, String host, String username, Integer port) throws Exception{
        Session session = null;
        if (port <= 0) {
            session = jsch.getSession(username,host);
        }
        else {
            session = jsch.getSession(username,host,port);
        }
        if(session == null){
            throw new Exception(host+"session is null");
        }
        session.setConfig(SESSION_CONFIG_STRICT_HOST_KEY_CHECKING,config.getSessionStrictHostKeyChecking());
        return session;
    }


    public boolean createDirectory(String pro_name) throws Exception {                      //在服务器上建立相关文件夹
        ChannelSftp sftp = this.createSftp();
        String Directory2[] = new String[]{"/"+pro_name+"/后期文件/原始文件",
                "/"+pro_name+"/模型文件/原始模型","/"+pro_name+"/模型文件/最终模型",
                "/"+pro_name+"/渲染文件/原始渲染","/"+pro_name+"/渲染文件/最终渲染",
        };
        String Driectory[] = new String[]{"/"+pro_name+"/jpg","/"+pro_name+"/后期文件",
                "/"+pro_name+"/模型文件","/"+pro_name+"/小样","/"+pro_name+"/渲染文件","/"+pro_name+"/资料"
        };
        sftp.cd(config.getRoot());
        for (String s : Driectory) {                           //创建一级目录
            this.createDirs(s,sftp);
            sftp.cd("/");
            sftp.cd(config.getRoot());
        }
        sftp.cd("/");                                                  //创建二级目录
        sftp.cd(config.getRoot());
        for (String s : Directory2) {
            this.createDirs(s,sftp);
            sftp.cd("/");
            sftp.cd(config.getRoot());                        //回到一级目录
        }
        this.disconnect(sftp);
        return true;
    }



    private boolean createDirs(String dirPath, ChannelSftp sftp) throws UnsupportedEncodingException, SftpException, NoSuchFieldException, IllegalAccessException {
        if (dirPath != null && !dirPath.isEmpty() && sftp != null) {
            String[] dirs = Arrays.stream(dirPath.split("/"))
                    .filter(StringUtils::isNotBlank)
                    .toArray(String[]::new);
//            Class cl = ChannelSftp.class;                                      //改变为gbk编码格式
//            Field f =cl.getDeclaredField("server_version");
//            f.setAccessible(true);
//            f.set(sftp, 2);
//            sftp.setFilenameEncoding("gbk");
            for (String dir : dirs) {
                try {
                    sftp.cd(dir);
                    log.info("Change directory {}", dir);
                } catch (SftpException e) {
                    try {
                        sftp.mkdir(dir);
                        log.info("Create directory {}", dir);
                    } catch (SftpException sftpException) {
                        log.error("Create directory failure, directory:{}", dir, sftpException);
                        sftpException.printStackTrace();
                    }
                    try {
                        sftp.cd(dir);
                        log.info("Change directory {}", dir);
                    } catch (SftpException sftpException) {
                        sftpException.printStackTrace();
                    }
                }
            }
            return true;
        }
        return false;
    }
}
